﻿#region ディレクティブを使用する

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

#endregion

namespace SmartPDA.Windows.Forms
{

	#region Class for TTF, TTC

	/// <summary>
	/// OpenTypeFont ファイルの OffsetTable を格納するクラスです。
	/// </summary>
	internal class TTFOffsetTable
	{
		/// <summary>
		/// OpenTypeFont フォントファイル形式の MajorVersion が格納されます。
		/// </summary>
		public ushort MajorVersion;

		/// <summary>
		/// OpenTypeFont フォントファイル形式の MinorVersion が格納されます。
		/// </summary>
		public ushort MinorVersion;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの NumOfTables が格納されます。Table Directory の数です。
		/// </summary>
		public ushort NumOfTables;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの SearchRange が格納されます。
		/// </summary>
		public ushort SearchRange;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの EntrySelector が格納されます。
		/// </summary>
		public ushort EntrySelector;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの RangeShift が格納されます。
		/// </summary>
		public ushort RangeShift;

		/// <summary>
		/// OpenTypeFont ファイルから読み込んだ OffsetTable が存在する先頭アドレス ( オフセット ) が格納されます。
		/// </summary>
		/// <remarks>
		/// 読み込んだ OpenTypeFont フォントが TrueType フォントの場合通常 Position プロパティの値は 0 です。
		/// TrueType Collection フォントの場合は、読み込まれた値が設定されます。
		/// </remarks>
		public long Position;

	}

	/// <summary>
	/// OpenTypeFont ファイルの TrueType Collection 形式のファイルヘッダを格納するクラスです。
	/// </summary>
	internal class TTCHeader
	{
		/// <summary>
		/// OpenTypeFont フォントファイル形式の MajorVersion が格納されます。
		/// </summary>
		public ushort MajorVersion;

		/// <summary>
		/// OpenTypeFont フォントファイル形式の MinorVersion が格納されます。
		/// </summary>
		public ushort MinorVersion;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの NumOfTables が格納されます。
		/// </summary>
		/// <remarks>
		/// NumOfTables プロパティに格納されている数が、この TTC ファイルに格納されているフォント数と等価です。
		/// </remarks>
		public long NumOfTables;

		/// <summary>
		/// OpenTypeFont ファイルに格納されているフォントの OffsetTable が格納されているアドレスが格納されます。
		/// </summary>
		public long[] OffsetTable;

		/// <summary>
		/// OpenTypeFont ファイルから読み込んだ TTCHeader が存在する先頭アドレス ( オフセット ) が格納されます。
		/// </summary>
		/// <remarks> 
		/// 通常 Position プロパティの値は 0 です。
		/// </remarks>
		public long Position;
	}

	/// <summary>
	/// OpenTypeFont ファイルの Table Directory が格納されるクラスです。
	/// </summary>
	internal class TableDirectory
	{
		/// <summary>
		/// Table Directory の Tag が格納されます。
		/// </summary>
		/// <remarks>
		/// GSUB, name 等のタグが格納されます。
		/// </remarks>
		public string Tag = string.Empty;

		/// <summary>
		/// Table Directory が指し示す Table のチェックサムが格納されます。
		/// </summary>
		public long CheckSum;

		/// <summary>
		/// Tag に示される Table が格納されているフォントファイル先頭からのアドレスが格納されます。 
		/// </summary>
		public long Offset;

		/// <summary>
		/// Tag に示される Table のサイズが格納されます。単位はバイトです。
		/// </summary>
		public long Length;

		/// <summary>
		/// この Table Directory が存在する先頭アドレス ( オフセット ) が格納されます。
		/// </summary>
		public long Position;
	}

	/// <summary>
	/// OpenTypeFont ファイルの NamingTable が格納されるクラスです。Naming Table は、Table Directory 内で指し示されます。
	/// </summary>
	internal class NamingTable
	{
		/// <summary>
		/// Naming Table の FormatSelector が格納されます。
		/// </summary>
		public ushort FormatSelector;

		/// <summary>
		/// Naming Table の NumberOfNameRecords が格納されます。
		/// </summary>
		public ushort NumberOfNameRecords;

		/// <summary>
		/// Naming Table の StorageOffset が格納されます。
		/// </summary>
		/// <remarks>
		/// StorageOffset プロパティは、Naming Table が指し示す文字列が格納されているアドレスが格納されます。
		/// ここで格納されるアドレスは、Naming Table のアドレス ( Position プロパティの値 ) からのオフセット位置になります。
		/// </remarks>
		public ushort StorageOffset;

		/// <summary>
		/// この Naming Table が存在する先頭アドレス ( オフセット ) が格納されます。
		/// </summary>
		public long Position;
	}

	/// <summary>
	/// OpenTypeFont ファイルの Name Record が格納されるクラスです。Name Record は、Naming Table 内で指し示されます。
	/// </summary>
	internal class NameRecord
	{
		/// <summary>
		/// Name Record の Platform ID が格納されます。
		/// </summary>
		public ushort PlatformID;

		/// <summary>
		/// Name Record の Encoding ID が格納されます。
		/// </summary>
		public ushort EncodingID;

		/// <summary>
		/// Name Record の Language ID が格納されます。
		/// </summary>
		public ushort LanguageID;

		/// <summary>
		/// Name Record の Name ID が格納されます。
		/// </summary>
		public ushort NameID;

		/// <summary>
		/// Name Record の PString Length が格納されます。単位はバイトです。
		/// </summary>
		public ushort StringLength;

		/// <summary>
		/// Name Record の String offset が格納されます。単位はバイトです。
		/// </summary>
		public ushort StringOffset;

		/// <summary>
		/// Name Record の String Offset プロパティが指し示す値が格納されます。
		/// </summary>
		public string Value = string.Empty;

		/// <summary>
		/// この Naming Table が存在する先頭アドレス ( オフセット ) が格納されます。
		/// </summary>
		public long Position;
	}

	/// <summary>
	/// OpenTypeFont ファイルの Name ID が格納されるクラスです。Name ID は、Naming Record 内で指し示されます。
	/// </summary>
	public class NameID
	{
		/// <summary>
		/// Name ID の Copyright notice が格納されます。
		/// </summary>
		public string Copyright = string.Empty;

		/// <summary>
		/// Name ID の Font Family name が格納されます。
		/// </summary>
		public string FamilyName = string.Empty;

		/// <summary>
		/// Name ID の Sub Family name が格納されます。
		/// </summary>
		public string SubFamilyName = string.Empty;

		/// <summary>
		/// Name ID の Unique font ID が格納されます。
		/// </summary>
		public string UID = string.Empty;

		/// <summary>
		/// Name ID の Full Font name が格納されます。
		/// </summary>
		public string FullFontName = string.Empty;

		/// <summary>
		/// Name ID の Version が格納されます。
		/// </summary>
		public string Version = string.Empty;

		/// <summary>
		/// Name ID の Postscript name が格納されます。
		/// </summary>
		public string PostscriptName = string.Empty;

		/// <summary>
		/// Name ID の Trademark が格納されます。
		/// </summary>
		public string Trademark = string.Empty;
	}

	#endregion

	/// <summary>
	/// 指定したパスの OpenTypeFont ファイルに含まれているフォント情報を読み込み OpenTypeFont クラスを返すクラスです。
	/// </summary>
	/// <remarks>
	/// コンストラクタもしくは Open メソッドのパラメータで OpenTypeFont ファイルを指定し、Read メソッドでファイルを読み込みます。
	/// Read メソッドでファイルを読み込むとフォントファイル内部を解析し、OpenTypeFont オブジェクト配列を返します。TTC 形式にも対応しています。
	/// </remarks>
	internal class OpenTypeFontReader
	{

		#region Constructor

		/// <summary>
		/// OpenTypeFontReader クラスのインスタンスを初期化します。
		/// </summary>
		public OpenTypeFontReader()
		{
		}

		/// <summary>
		/// OpenTypeFontReader クラスのインスタンスを初期化します。
		/// </summary>
		/// <param name="path">読み込む OpenTypeFont ファイルのパス</param>
		public OpenTypeFontReader(string path)
		{
			this.Open(path);
		}

		#endregion

		#region FileStream

		/// <summary>
		/// Open メソッドで OpenTypeFont ファイルを読み込む FileStream オブジェクト
		/// </summary>
		private FileStream File;

		/// <summary>
		/// パラメータに指定したフォントファイルを FileStream で開きます。
		/// </summary>
		/// <param name="path">開くフォントファイルのパス</param>
		public void Open(string path)
		{
			this.File = new FileStream(path, FileMode.Open, FileAccess.Read);
		}

		/// <summary>
		/// Open メソッドで開いた FileStream を閉じます。
		/// </summary>
		public void Close()
		{
			this.File.Close();
		}

		/// <summary>
		/// Open メソッドで開いている FileStream の現在ポジションを取得します。
		/// </summary>
		public long Position
		{
			get { return this.File.Position; }
			set { this.File.Position = value; }
		}

		#endregion

		#region HeaderCheck

		/// <summary>
		/// TTFHeader オブジェクトに指定されているフォントファイルが TrueType Font Collection ファイルであるかどうか示す値を取得します。
		/// </summary>
		/// <returns>True なら指定したファイルは TTC ファイルです。False の場合は、TTF ファイルです。</returns>
		public bool IsTTC()
		{
			return this.IsTTC(this.File);

		} // IsTTC

		/// <summary>
		/// 指定したフォントファイルが TrueType Font Collection ファイルであるかどうかを示す値を取得します。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>True なら指定したファイルは TTC ファイルです。False の場合は、TTF ファイルです。</returns>
		public bool IsTTC(FileStream fs)
		{
			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// ファイルの先頭へ移動
			fs.Position = 0;

			// 先頭 4バイト読み込み
			if (new String(br.ReadChars(4)).Equals("ttcf"))
			{
				return true;
			}

			fs.Position = 0;
			return false;

		} // IsTTC

		#endregion

		#region Read Font file

		/// <summary>
		/// Open メソッドで開いたフォントファイルを読み込み OpenTypeFont オブジェクトを返します。
		/// </summary>
		/// <remarks>
		/// TTF ファイルと TTC ファイルを判別して OpenTypeFont オブジェクトを返します。
		/// TTF ファイルの場合一つの OpenTypeFont オブジェクトが帰ってきます。TTC ファイルの場合複数の OpenTypeFont オブジェクトが帰ってきます。
		/// </remarks>
		/// <returns>OpenTypeFont オブジェクト配列</returns>
		public OpenTypeFont[] Read()
		{
			// TTC ファイル
			if (this.IsTTC())
			{
				return this.ReadTTC();
			}

			// TTF ファイル
			else
			{
				return this.ReadTTF();
			}

		} // Read

		/// <summary>
		/// TTC ファイルを読み込み、フォントファイルに含まれている複数のフォントを OpenTypeFont オブジェクトにして返します。Read メソッドに呼ばれます。
		/// </summary>
		/// <returns>OpenTypeFont オブジェクト配列</returns>
		private OpenTypeFont[] ReadTTC()
		{
			// 一時配列を宣言
			List<OpenTypeFont> tmpArray = new List<OpenTypeFont>();

			// TTC ヘッダ情報を読み込みます
			TTCHeader toc = this.GetTTCHeader(this.File);

			// 読み込み用 OpenTypeFont クラスの宣言
			OpenTypeFont tf;

			// OffsetTable 分のフォント情報を読み込みます
			for (long i = 0; i < toc.OffsetTable.Length; i++)
			{
				tf = new OpenTypeFont();

				// TTF フォントの読み込み
				tf.Read(this.File, toc.OffsetTable[i]);

				// NameRecord の値を取得
				tf.GetNameID(this.File);

				// 一時配列に追加
				tmpArray.Add(tf);

			}

			// 配列として返す
			return tmpArray.ToArray();

		} // ReadTTC

		/// <summary>
		/// TTC 形式のフォントファイルから TTC ヘッダを読み込みます。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream</param>
		/// <returns>TTCHeader オブジェクト</returns>
		private TTCHeader GetTTCHeader(FileStream fs)
		{
			// TTF_OFFSET_TABLE インスタンス作成
			TTCHeader ot = new TTCHeader();

			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// ポジション移動
			fs.Seek(4, SeekOrigin.Begin);

			// 各情報読み込み
			ot.Position = fs.Position;
			ot.MajorVersion = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.MinorVersion = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.NumOfTables = OpenTypeFont.SwapInt(br.ReadBytes(4));

			ot.OffsetTable = new long[ot.NumOfTables];
			for (long i = 0; i < ot.NumOfTables; i++)
			{
				ot.OffsetTable[i] = OpenTypeFont.SwapInt(br.ReadBytes(4));
			}

			return ot;
		}

		/// <summary>
		/// TTF ファイルを読み込み、OpenTypeFont オブジェクトを返します。Read メソッドに呼ばれます。
		/// </summary>
		/// <returns>OpenTypeFont オブジェクト配列</returns>
		private OpenTypeFont[] ReadTTF()
		{
			// 一時配列を宣言
			List<OpenTypeFont> tmpArray = new List<OpenTypeFont>();

			// OpenTypeFont クラスの宣言
			OpenTypeFont tf = new OpenTypeFont();

			// テーブル類読み込み
			tf.Read(this.File);

			// NameRecord の値を取得
			tf.GetNameID(this.File);

			// 一時配列に追加
			tmpArray.Add(tf);

			// 配列として返す
			return tmpArray.ToArray();

		} // ReadTTF

		#endregion

	} // OpenTypeFontReader

	/// <summary>
	/// TTF 形式のフォント情報を格納するクラス
	/// </summary>
	internal class OpenTypeFont
	{

		#region Properties

		/// <summary>
		/// Read メソッドで FileStream から読み込むときの先頭からのオフセットアドレスを取得または設定する。
		/// </summary>
		public long FileReadOffset = 0;

		/// <summary>
		/// このフォントの Offset Table を格納します。
		/// </summary>
		public TTFOffsetTable OffsetTable;

		/// <summary>
		/// このフォントの Naming Table を格納します。
		/// </summary>
		public NamingTable NamingTable;

		/// <summary>
		/// このフォントの複数の Table Directory を格納します。
		/// </summary>
		public Dictionary<string, TableDirectory> TableDirectories = new Dictionary<string, TableDirectory>();

		/// <summary>
		/// このフォントの複数の Name Records を格納します。
		/// </summary>
		public List<NameRecord> NameRecords = new List<NameRecord>();

		/// <summary>
		/// このフォントのデフォルトの Name ID を格納します。
		/// </summary>
		/// <remarks>
		/// デフォルトの Name ID というのは、 Platform ID = 0, Language ID = 0 の Name ID である。
		/// </remarks>
		public NameID DefaultNameID = new NameID();

		/// <summary>
		/// このフォントの現在のロケールの Name ID を格納します。
		/// </summary>
		/// <remarks>
		/// 実行している環境の LCID ( System.Globalization.CultureInfo クラスの LCID プロパティ ) と同じ Language ID の Name ID である。
		/// </remarks>
		public NameID CurrentCultureNameID = new NameID();

		/// <summary>
		/// Read メソッドで読み込んだフォントファイルのパスを格納します。
		/// </summary>
		public string FontPath = "";

		#endregion

		/// <summary>
		/// FileStream に指定されているフォントファイルから TTF 形式のフォントを読み込みます。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream</param>
		/// <returns>正しくフォントファイルの読み込みができた場合 true。何らかの失敗があった場合は false が返ります。</returns>
		public bool Read(FileStream fs)
		{
			return this.Read(fs, 0);
		}

		/// <summary>
		/// FileStream に指定されているフォントファイルの指定の位置から TTF 形式のフォントを読み込みます。TTC ファイルに対して使用するメソッドです。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream</param>
		/// <param name="offsetOffSetTable">Offset Table を読み込むファイルの先頭からのアドレス ( TTCHeader.OffsetTable[] の値 )。</param>
		/// <returns>正しくフォントファイルの読み込みができた場合 true。何らかの失敗があった場合は false が返ります。</returns>
		public bool Read(FileStream fs, long offsetOffSetTable)
		{
			try
			{
				// フォントのファイル名を取得
				this.FontPath = fs.Name;

				// オフセットテーブルの先頭に移動
				fs.Seek(offsetOffSetTable, SeekOrigin.Begin);

				this.GetOffSetTable(fs);
				this.GetTableDirectories(fs);
				this.GetNamingTable(fs);
				this.GetNameRecords(fs);

				return true;

			}
			catch
			{
				return false;
			}

		}

		#region GetTables

		/// <summary>
		/// FileStream から OffsetTable を取得して OffsetTable プロパティに TTFOffsetTable オブジェクトを格納します。Read メソッドから呼ばれます。 
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>TTFOffsetTable オブジェクト</returns>
		private void GetOffSetTable(FileStream fs)
		{
			// TTF_OFFSET_TABLE インスタンス作成
			TTFOffsetTable ot = new TTFOffsetTable();

			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// 各情報を格納
			ot.Position = fs.Position;
			ot.MajorVersion = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.MinorVersion = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.NumOfTables = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.SearchRange = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.EntrySelector = OpenTypeFont.SwapShort(br.ReadBytes(2));
			ot.RangeShift = OpenTypeFont.SwapShort(br.ReadBytes(2));

			// TTFOffsetTable オブジェクトの格納
			this.OffsetTable = ot;
		}

		/// <summary>
		/// FileStram から Table Directory を取得し TableDirectory オブジェクトを返します。GetTableDirectories メソッドから呼ばれます。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>TableDirectory オブジェクト</returns>
		private TableDirectory GetTableDirectory(FileStream fs)
		{
			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// TABLE_DIRECTORY 取得
			TableDirectory ot = new TableDirectory();

			// 各情報の格納
			ot.Position = fs.Position;
			ot.Tag = Encoding.ASCII.GetString(br.ReadBytes(4), 0, 4);
			ot.CheckSum = OpenTypeFont.SwapInt(br.ReadBytes(4));
			ot.Offset = OpenTypeFont.SwapInt(br.ReadBytes(4));
			ot.Length = OpenTypeFont.SwapInt(br.ReadBytes(4));

			return ot;

		} // GetOffsetTable

		/// <summary>
		/// FileStram から Table Directory を取得し TableDirectory オブジェクトを TableDirectoryArray に格納します。Read メソッドから呼ばれます。 
		/// GetOffSetTable メソッドを実行した直後に呼ぶ必要があります。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>格納した TableDirectory オブジェクト数</returns>
		private int GetTableDirectories(FileStream fs)
		{
			TableDirectory ot;

			// OffsetTable の取得
			for (int i = 0; i < this.OffsetTable.NumOfTables; i++)
			{

				// OffsetTable の取得
				ot = this.GetTableDirectory(fs);

				//Console.WriteLine(ot.Tag + " " + ot.Position.ToString());

				// OffsetTable の格納
				this.TableDirectories.Add(ot.Tag, ot);
			}

			return this.TableDirectories.Count;

		} // GetOffsetTables

		/// <summary>
		/// FileStram から Naming Table を取得し NamingTable オブジェクトを NamingTable プロパティに格納します。Read メソッドから呼ばれます。
		/// GetTableDirectories メソッドを実行した直後に呼ぶ必要があります。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		private void GetNamingTable(FileStream fs)
		{
			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// NamingTable オフセット位置に移動
			fs.Seek(this.TableDirectories["name"].Offset, SeekOrigin.Begin);

			// NamingTable 読み込み
			NamingTable nt = new NamingTable();

			// 各情報の格納
			nt.FormatSelector = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nt.NumberOfNameRecords = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nt.StorageOffset = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nt.Position = fs.Position;

			// NamingTable 格納
			this.NamingTable = nt;

		} // GetNamingTable

		/// <summary>
		/// FileStream から Name Record を取得し NameRecord オブジェクトを返します。GetNameRecords メソッドから呼ばれます。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>NameRecord オブジェクト</returns>
		private NameRecord GetNameRecord(FileStream fs)
		{
			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// NAME_RECORD 取得
			NameRecord nr = new NameRecord();

			// 各情報の格納
			nr.Position = fs.Position;
			nr.PlatformID = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nr.EncodingID = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nr.LanguageID = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nr.NameID = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nr.StringLength = OpenTypeFont.SwapShort(br.ReadBytes(2));
			nr.StringOffset = OpenTypeFont.SwapShort(br.ReadBytes(2));

			return nr;

		} // GetNameRecords

		/// <summary>
		/// FileStream から Name Record を取得し NameRecord オブジェクトを NameRecords コレクションに格納します。Read メソッドから呼ばれます。
		/// GetNamingTable メソッドを実行した直後に呼ぶ必要があります。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <returns>格納した NameRecord オブジェクト数</returns>
		private int GetNameRecords(FileStream fs)
		{

			// NameRecord の取得
			for (int i = 0; i < this.NamingTable.NumberOfNameRecords; i++)
			{
				// NameRecord の格納
				this.NameRecords.Add(this.GetNameRecord(fs));
			}

			return this.NameRecords.Count;

		} // GetNameRecords

		#endregion

		#region GetNameID

		/// <summary>
		/// パラメータに指定した NameRecord オブジェクトの値を FileStream から読み込み NameRecord.Value プロパティに格納します。GetNameID メソッドから呼ばれます。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		/// <param name="nr">値の読み込みを行う NameRecord オブジェクト</param>
		/// <returns>読み込んだ値の文字列</returns>
		public string GetNameIDField(FileStream fs, NameRecord nr)
		{

			// BinaryReader インスタンス作成
			BinaryReader br = new BinaryReader(fs);

			// ポジション移動
			fs.Seek(
				this.TableDirectories["name"].Offset +
				this.NamingTable.StorageOffset +
				nr.StringOffset,
				SeekOrigin.Begin);

			// 読み込み
			byte[] byteArray = br.ReadBytes(nr.StringLength);

			// NameRecord に格納
			// 
			// 値の Encoding の方法
			//	Platform ID = 0 ( Apple Unicode ) → Unicode ( BigEndianUnicode )
			//  Platform ID = 1 ( Macintosh ) → Default ( 現在動作している環境のコードページ )
			//  Platform ID = 2 ( ISO ) → ASCII
			//  Platform ID = 3 ( Microsoft ) && Encoding ID = 0 → Default
			//  Platform ID = 3 ( Microsoft ) && Encoding ID = 1 → Unicode ( BigEndianUnicode )
			// 

			// Apple Unicode
			if (nr.PlatformID == 0)
			{
				nr.Value = Encoding.BigEndianUnicode.GetString(byteArray, 0, byteArray.Length);
			}

			// ISO
			else if (nr.PlatformID == 2)
			{
				nr.Value = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length);
			}

			// Microsoft, Unicode 
			else if (nr.PlatformID == 3 && nr.EncodingID == 1)
			{
				nr.Value = Encoding.BigEndianUnicode.GetString(byteArray, 0, byteArray.Length);
			}

			// Default
			else
			{
				nr.Value = Encoding.Default.GetString(byteArray, 0, byteArray.Length);
			}

			return nr.Value;

		} // GetNameIDField

		/// <summary>
		/// FileStream から NameRecords コレクションに格納されている NameRecord オブジェクトの値を取得し格納します。
		/// </summary>
		/// <param name="fs">フォントファイルを開いている FileStream インスタンス。</param>
		public int GetNameID(FileStream fs)
		{

			for (int i = 0; i < this.NameRecords.Count; i++)
			{
				this.GetNameIDField(fs, (this.NameRecords[i]));
			}

			// 取得した値を設定
			this.SetNameID();

			return this.NameRecords.Count;

		}

		/// <summary>
		/// GetNameID メソッドによって読み込まれた NameRecord オブジェクトの値を、DefaultNameID プロパティ、CurrentCultureNameID プロパティに格納します。
		/// </summary>
		public void SetNameID()
		{
			// LDID の取得
			System.Globalization.CultureInfo ci = System.Globalization.CultureInfo.CurrentCulture;
			NameRecord tmpRecord;

			// すべての NameRecord オブジェクトを取り出す
			for (int i = 0; i < this.NameRecords.Count; i++)
			{
				tmpRecord = this.NameRecords[i];

				// デフォルト？ LCID の探索
				//
				// Platform ID = 1, Encoding ID = 0
				// の NameRecord を、デフォルト( Roman ) として探索する。

				if (tmpRecord.PlatformID == 1 && tmpRecord.EncodingID == 0)
				{
					this.SetNameIDSwitch(this.DefaultNameID, tmpRecord);
				}

				// 現在の LCID と同じ NameID の探索
				//
				// Platform ID = 3, Language ID = LCID 
				// の NameRecord を、CurrentCulture のフォント情報として探索する。

				if (tmpRecord.PlatformID == 3 && tmpRecord.LanguageID == ci.LCID)
				{
					this.SetNameIDSwitch(this.CurrentCultureNameID, tmpRecord);
				}

			}

		} // SetNameID

		/// <summary>
		/// NameRecord オブジェクトの NameID プロパティの値を、NameID オブジェクトの対応するプロパティに格納します。
		/// </summary>
		/// <param name="id">値を格納する NameID オブジェクト</param>
		/// <param name="nr">NameRecord オブジェクト</param>
		private void SetNameIDSwitch(NameID id, NameRecord nr)
		{

			switch (nr.NameID)
			{
				case (0):
					{
						id.Copyright = nr.Value;
						break;
					}
				case (1):
					{
						id.FamilyName = nr.Value;
						break;
					}
				case (2):
					{
						id.SubFamilyName = nr.Value;
						break;
					}
				case (3):
					{
						id.UID = nr.Value;
						break;
					}
				case (4):
					{
						id.FullFontName = nr.Value;
						break;
					}
				case (5):
					{
						id.Version = nr.Value;
						break;
					}
				case (6):
					{
						id.PostscriptName = nr.Value;
						break;
					}
				case (7):
					{
						id.Trademark = nr.Value;
						break;
					}

			}

		} // SetNameIDSwitch

		#endregion

		#region Method

		/// <summary>
		/// パラメータに指定された byte型の配列をビッグエンディアンからリトルエンディアンに変換し、UInt16 型にして返します。
		/// </summary>
		/// <param name="byteArray">変換する byte型配列</param>
		/// <returns>変換後の UInt16 数値</returns>
		public static ushort SwapShort(byte[] byteArray)
		{
			Array.Reverse(byteArray, 0, byteArray.Length);
			return BitConverter.ToUInt16(byteArray, 0);
		}

		/// <summary>
		/// パラメータに指定された byte型の配列をビッグエンディアンからリトルエンディアンに変換し、UInt32 型にして返します。
		/// </summary>
		/// <param name="byteArray">変換する byte型配列</param>
		/// <returns>変換後の UInt16 数値</returns>
		public static uint SwapInt(byte[] byteArray)
		{
			Array.Reverse(byteArray, 0, byteArray.Length);
			return BitConverter.ToUInt32(byteArray, 0);
		}

		#endregion

	} // OpenTypeFont

}
